// 扩展4-4 c++中的多线程-demo4 模拟火车售票系统
/**
 * 原文链接：https://blog.csdn.net/luoweifu/article/details/46835437
 * 
 * CreateMutex、WaitForSingleObject、ReleaseMutex
 * 
 *从【Demo2】中可以看出，虽然创建的子线程都正常执行起来了，但输出的结果并不是我们预期的效果。我们预期的效果是每输出一条语句后自动换行，但结果却并非都是这样。这是因为在线程执行时没有做同步处理，比如第一行的输出，主线程输出“主线程 ===”后时间片已用完，这时轮到子线程1输出，在子线程输出“线程1 —”后时间片也用完了，这时又轮到主线程执行输出“0”，之后又轮到子线程1输出“0”。于是就出现了“主线程 === 线程1 — 0 0”的结果。

          主线程：cout << “主线程 === ” << i << endl;
          子线程：cout << pThreadData->strThreadName << ” — ” << i << endl;

 * 为避免出现这种情况，我们对线程做一些简单的同步处理，这里我们用互斥量(Mutex)，关于互斥量(Mutex)的概念，请看《编程思想之多线程与多进程(2)——线程优先级与线程安全》一文；更多C++线程同步的处理，请看下一节。

 *在使用互斥量进行线程同步时会用到以下几个函数：

      HANDLE WINAPI CreateMutex(
          LPSECURITY_ATTRIBUTES lpMutexAttributes,        //线程安全相关的属性，常置为NULL
          BOOL                  bInitialOwner,            //创建Mutex时的当前线程是否拥有Mutex的所有权
          LPCTSTR               lpName                    //Mutex的名称
      );
 * 说明： lpMutexAttributes也是表示安全的结构，与CreateThread中的lpThreadAttributes功能相同，表示决定返回的句柄是否可被子进程继承，如果为NULL则表示返回的句柄不能被子进程继承。bInitialOwner表示创建Mutex时的当前线程是否拥有Mutex的所有权，若为TRUE则指定为当前的创建线程为Mutex对象的所有者，其它线程访问需要先ReleaseMutex。lpName为Mutex的名称。

      DWORD WINAPI WaitForSingleObject(
          HANDLE hHandle,                             //要获取的锁的句柄
          DWORD  dwMilliseconds                           //超时间隔
      );
 * 说明：
    WaitForSingleObject的作用是等待一个指定的对象(如Mutex对象)，直到该对象处于非占用的状态(如Mutex对象被释放)或超出设定的时间间隔。除此之外，还有一个与它类似的函数WaitForMultipleObjects，它的作用是等待一个或所有指定的对象，直到所有的对象处于非占用的状态，或超出设定的时间间隔。
    hHandle：要等待的指定对象的句柄。dwMilliseconds：超时的间隔，以毫秒为单位；如果dwMilliseconds为非0，则等待直到dwMilliseconds时间间隔用完或对象变为非占用的状态，如果dwMilliseconds 为INFINITE则表示**无限等待**，直到等待的对象处于非占用的状态。

        BOOL WINAPI ReleaseMutex(HANDLE hMutex);

 *------------------------
 * demo4 模拟火车售票系统
 * 为进一步理解线程同步的重要性和互斥量的使用方法，我们再来看一个例子。

 * 买火车票是大家春节回家最为关注的事情，我们就简单模拟一下火车票的售票系统(为使程序简单，我们就抽出最简单的模型进行模拟)：有500张从北京到赣州的火车票，在8个窗口同时出售，保证系统的稳定性和数据的**原子性**。
*/
// #include "stdafx.h"

#include <iostream>


int main(void)
{
  /**
   * 见C_Multiple/study/day19/1_multithreading_3/expand_4/e_4_4
  */
  printf("-------------end------------------\n");
  return 0;
}